<?php

namespace App\Recharge\Api;

use GuzzleHttp\Promise\PromiseInterface;
use Illuminate\Http\Client\Response;
use Throwable;
use Exception;
use Illuminate\Http\Request;
use App\Recharge\Bean\BasicInformation;
use App\Recharge\Bean\FuluUnitPriceBean;
use App\Recharge\Bean\ApiNotifyDataBean;
use App\Models\Admin\InterfaceConfiguration;
use App\Recharge\Bean\SupplierApiConfigBean;


class Fulu extends AbstractApi
{
    /**
     * @param string $appid
     * @param string $app_key
     * @param string $method
     * @param array $biz_content
     * @return array
     */
    function fuluData(string $appid, string $app_key, string $method, array $biz_content): array
    {
        // 配置
        $array = [
            'app_key'       => $app_key, //开放平台分配给商户的app_key
            'method'        => $method,//接口方法名称
            'timestamp'     => date('Y-m-d H:i:s'),//时间
            'version'       => '2.0',//调用的接口版本
            'format'        => 'json',//接口请求或响应格式
            'charset'       => 'utf-8',//请求使用的编码格式，如utf-8等
            'sign_type'     => 'md5',//签名加密类型，目前仅支持md5
            'app_auth_token'=> '',//授权码，固定值为'',
            'biz_content'   => array2json($biz_content)
        ];
        $array['sign'] = $this->sign($array, $appid);
        return $array;
    }

    /**
     * @param array $resp
     * @return array
     */
    function apiResult(array $resp): array
    {
        return isset($resp['result']) ? json2array($resp['result']) : [];
    }

    /**
     * @param string $url
     * @param array $data
     * @return array
     */
    function apiSend(string $url, array $data): array
    {
        return httpClient()->asJson()->post($url, $data)->json() ?? [];
    }

    /**
     * @param string $appid
     * @param string $app_key
     * @param string $url
     * @return float|int|string
     */
    function balance(string $appid, string $app_key, string $url = 'fulu.user.info.get'): float|int|string
    {
        $data = $this->fuluData($appid, $app_key, 'fulu.user.info.get', []);
        $resp = $this->apiSend($url, $data);
        return data_get($this->apiResult($resp), 'balance', 0);
    }

    /**
     * 福禄商品查询
     *
     * @param InterfaceConfiguration $api
     * @param SupplierApiConfigBean $config
     * @param string|int $goodsId
     * @return FuluUnitPriceBean
     */
    function good(InterfaceConfiguration $api, SupplierApiConfigBean $config, string|int $goodsId): FuluUnitPriceBean
    {
        $bean = new FuluUnitPriceBean();
        try {
            $biz_content = [
                'first_category_id' => '',//商品分类Id（一级）
                'second_category_id'=> '',//商品分类Id（二级）
                'third_category_id' => '',//商品分类Id（三级）
                'product_id'        => $goodsId,
                'product_name'      => '',//商品名称
                'product_type'      => '',//库存类型：卡密、直充
                'face_value'        => '',//面值
            ];
            $array = $this->fuluData($config->getAppid(), $config->getSecretKey(), 'fulu.goods.info.get', $biz_content);
            // 访问
            $good = $this->apiSend($api->good_url, $array);
            $bean->setResponse($good);
            // 判断
            if (!isset($good['code'])) {
                throw new Exception("未返回code");
            }
            $result = $this->apiResult($good);
            if (!isset($result['purchase_price'])) {
                throw new Exception("未返回价格");
            }
            $bean->setUnitPrice($result['purchase_price']);
            $bean->setResult(true);
        } catch (Throwable $e) {
            $bean->setErrMessage($e->getMessage());
        } finally {
            return $bean;
        }
    }


    /**
     * 通用
     *
     * @param array $data
     * @param string $key
     * @return string
     */
    public function sign(array $data, string $key): string
    {
        //签名步骤一：把字典json序列化
        $json = json_encode( $data, 320 );
        //签名步骤二：转化为数组
        $jsonArr = preg_split('/(?<!^)(?!$)/u', $json );
        //签名步骤三：排序
        sort( $jsonArr );
        //签名步骤四：转化为字符串
        $string = implode( '', $jsonArr );
        //签名步骤五：在string后加入secret
        $string = $string . $key;
        //签名步骤六：MD5加密
        return strtolower( md5( $string ) );
    }


    /**
     * @inheritDoc
     */
    public function rechargeData(BasicInformation $bean): array
    {
        // 组装
        $productType = '';
        if ($bean->getProductType() == 0){
            $productType = '直充';
        }
        elseif ($bean->getProductType() == 1){
            $productType = '卡密';
        }
        $biz_content = [
            'product_id'        => $bean->getGoodsId(), //商品编号id
            'customer_order_no' => $bean->getOrderNo(),//订单号
            'charge_account'    => $bean->getAccount(), //要充值的用户
            'buy_num'           => $bean->getRechargeNum() * $bean->getStartCharging(),
            'charge_game_name'  => $bean->getGoodsName(),
            'charge_game_region'=> $bean->getGameAreaName(), //游戏区名称
            'charge_game_srv'   => $bean->getGameServerName(), //游戏服名称
            'charge_type'       => $productType,//充值类型
            'charge_password'   => '',//充值密码
            'charge_ip'         => $bean->getIp(),//获取用户当前的ip
            'contact_qq'        => '',//联系QQ
            'contact_tel'       => '',//联系电话
            'remaining_number'  => '',//剩余数量
            'charge_game_role'  => '',//充值游戏角色
            'customer_price'    => $bean->getUnitPrice(),
            'external_biz_id'   => ''
        ];
        return $this->fuluData($bean->getSupplierNum(), $bean->getSecretKey(), 'fulu.order.direct.add', $biz_content);
    }

    /**
     * @param InterfaceConfiguration $api
     * @param Request $request
     * @return ApiNotifyDataBean
     */
    public function apiNotifyLogic(InterfaceConfiguration $api, Request $request): ApiNotifyDataBean
    {
        $status = $request->input('order_status', '');
        $order_sn = $request->input('customer_order_no', '');
        return $this->apiNotifyData($order_sn, $status)->setExecute(in_array($status, ['success', 'failed']))->setRechargeSuccess($status == 'success');
    }
}
